package org.springblade.common.utils;

import java.util.Objects;
import java.util.regex.Pattern;

/**
 * SQL 注入验证工具类
 *
 * 提供SQL注入检查和处理相关的方法，以帮助提高应用程序的安全性
 */
public class SqlInjectionUtils {
	/**
	 * SQL语法检查正则：符合两个关键字（有先后顺序）才算匹配
	 */
	private static final Pattern SQL_SYNTAX_PATTERN = Pattern.compile("(insert|delete|update|select|create|drop|truncate|grant|alter|deny|revoke|call|execute|exec|declare|show|rename|set)" +
		"\\s+.*(into|from|set|where|table|database|view|index|on|cursor|procedure|trigger|for|password|union|and|or)|(select\\s*\\*\\s*from\\s+)" +
		"|if\\s*\\(.*\\)|select\\s*\\(.*\\)|substr\\s*\\(.*\\)|substring\\s*\\(.*\\)|char\\s*\\(.*\\)|concat\\s*\\(.*\\)|benchmark\\s*\\(.*\\)|sleep\\s*\\(.*\\)|(and|or)\\s+.*", Pattern.CASE_INSENSITIVE);
	/**
	 * 使用'、;或注释截断SQL检查正则
	 */
	private static final Pattern SQL_COMMENT_PATTERN = Pattern.compile("'.*(or|union|--|#|/\\*|;)", Pattern.CASE_INSENSITIVE);

	/**
	 * SQL语法检查正则: 准确率更高
	 */
	private static final Pattern SQL_INJECTION_PATTERN = Pattern.compile(
		"(?i)\\b(ALTER|CREATE|DELETE|DROP|EXEC(UTE)?|INSERT( +INTO)?|MERGE|SELECT|UPDATE|UNION( +ALL)?)\\b" +
			"|'|;|--|\\/\\*|\\*\\/|@@|\\b(AND|OR)\\b\\s*([^\\s]+\\s*=\\s*[^\\s]+|1\\s*=\\s*1)" +
			"|\\b(WAITFOR|DELAY)\\b\\s+\\'\\d{0,4}\\'" +
			"|\\b(SLEEP|BENCHMARK)\\b\\s*\\(\\s*\\d+\\s*\\)" +
			"|\\b(LOAD_FILE|INTO_FILE)\\b\\s*\\("
	);

	// 精准匹配基于时间延迟的 SQL 注入攻击
	private static final Pattern SQL_INJECTION_PATTERN_V2 = Pattern.compile(
		"(?i)" +  // 不区分大小写
			"(?:" +   // 开始非捕获组

			// 匹配 SLEEP 函数调用（带数字参数）
			"\\bSLEEP\\s*\\(\\s*\\d+\\s*\\)" +
			"|" +

			// 匹配 BENCHMARK 函数调用
			"\\bBENCHMARK\\s*\\(\\s*\\d+\\s*," +
			"|" +

			// 匹配 WAITFOR DELAY 语句
			"\\bWAITFOR\\s+DELAY\\s+['\"]\\d{0,3}:\\d{0,3}:\\d{0,3}['\"]" +
			"|" +

			// 匹配嵌套 SELECT 结构（如 (SELECT*FROM(...))
			"\\(\\s*SELECT\\s*\\*\\s*FROM\\s*\\(" +
			"|" +

			// 匹配时间盲注常见结构：AND (SELECT ...)
			"\\bAND\\s*\\(\\s*SELECT" +
			"|" +

			// 匹配注释结尾（# 或 --）
			"[#]|--" +

			")"    // 结束非捕获组
	);

	/**
	 * 检查参数是否存在 SQL 注入
	 *
	 * @param value 检查参数
	 * @return true 非法 false 合法
	 */
	public static boolean check(String value) {
		Objects.requireNonNull(value);
		// 处理是否包含SQL注释字符 || 检查是否包含SQL注入敏感字符
		return SQL_COMMENT_PATTERN.matcher(value).find() || SQL_SYNTAX_PATTERN.matcher(value).find();
	}

	/**
	 * 检查参数是否存在 SQL 注入
	 *
	 * @param value 检查参数
	 * @return true 非法 false 合法
	 */
	public static boolean checkV2(String value) {
		Objects.requireNonNull(value);
		// 处理是否包含SQL注释字符 || 检查是否包含SQL注入敏感字符
		return SQL_INJECTION_PATTERN.matcher(value).find();
	}

	/**
	 * 检查参数是否存在 SQL 注入
	 *
	 * @param value 检查参数
	 * @return true 非法 false 合法
	 */
	public static boolean checkV3(String value) {
		Objects.requireNonNull(value);
		// 处理是否包含SQL注释字符 || 检查是否包含SQL注入敏感字符
		return SQL_INJECTION_PATTERN.matcher(value).find();
	}


	/**
	 * 刪除字段转义符单引号双引号
	 *
	 * @param text 待处理字段
	 */
	public static String removeEscapeCharacter(String text) {
		Objects.nonNull(text);
		return text.replaceAll("\"", "").replaceAll("'", "");
	}

	public static void main(String[] args) {
		System.err.println(checkV2("0b1v7Y2w3kst953QaM3w3Kn1hJ2v7Y2K AND (SELECT*FROM(SELECT(SLEEP(3)))jgiq) limit 1#"));
		System.err.println(check("0b1v7Y2w3kst953QaM3w3Kn1hJ2v7Y2K AND (SELECT*FROM(SELECT(SLEEP(3)))jgiq) limit 1#"));
		System.err.println(checkV3("0b1v7Y2w3kst953QaM3w3Kn1hJ2v7Y2K AND (SELECT*FROM(SELECT(SLEEP(3)))jgiq) limit 1#"));
		System.err.println(checkV2("%20AND%20%28SELECT%2AFROM%28SELECT%28SLEEP%283%29%29%29qpgo%29%20limit%201%23"));
		System.err.println(checkV2("%20union%20select%201%2C2--%20"));
	}
}
